package top.mysql.SQL2;

/**
 *      索引使用规则
 *
 *
 */
public class Indexes2 {
/**
 *      --------------------------索引的使用规则 总结---------------------
 *
 *      索引的概述：
 *          索引是高效获取数据的数据结构
 *
 *      索引结构：
 *          B+树 索引
 *          Hash 索引
 *
 *      索引的分类：
 *          主键索引    唯一索引    常规索引    全文索引    单列索引    联合索引
 *          聚集索引    二级索引
 *
 *      索引的语法：
 *          create [unique] index 索引名 on 表名(字段名...);
 *          drop index 索引名  from 表名;
 *          show index from 表名;
 *
 *      SQL性能分析：
 *          执行频率    慢查询日志   profile   explain(常用)
 *
 *      索引的使用：
 *          联合索引    索引失效    SQL提示   覆盖索引    前缀索引    单列/联合索引
 *
 */
/**
 *
 *      --------------------------最左前缀法则---------------------
 *
 *      如果索引了多列(联合索引)，要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始，并且不跳过索引中的列。
 *      如果跳跃某一列，索引将会部分失效(后面的字段索引失效)。
 *
 *      最左前缀法则与联合索引创建时放入字段的顺序有关，而与where后编写顺序，字段顺序无关
 *
 *      注意 ： 最左前缀法则中指的最左边的列，是指在查询时，联合索引的最左边的字段(即是第一个字段)必须存在，
 *      与我们编写SQL时，条件编写的先后顺序无关。
 *
 *
 *      --------------------------范围查询---------------------
 *
 *      联合索引中，出现范围查询(>,<)，范围查询右侧的列索引失效。(与代码顺序无关，而是和字段顺序相关)
 *
 *      在业务允许的情况下，尽可能的使用类似于 >= 或 <= 这类的范围查询，而避免使用 > 或 <
 *
 *      --------------------------索引失效---------------------
 *
 *      不要在索引列上进行运算操作， 索引将失效。
 *
 *      字符串类型字段使用时，不加引号，索引将失效。(隐式类型转换导致索引失效)
 *
 *      如果仅仅是尾部模糊匹配，索引不会失效。如果是头部模糊匹配，索引失效。比如   '%工程' '_件'
 *
 *      如果or前的条件中的列有索引，而后面的列中没有索引，那么涉及的索引都不会被用到。or前后字段都要有索引
 *      (联合索引不符合最左前缀法则也一样)
 *
 *      数据分布影响：如果MySQL评估使用索引比全表更慢，则不使用索引(很少数据符合走索引，大量符合走全表扫描)
 *                 is null 和 is not null走不走索引不是固定的，而是取决于数据分布情况
 *
 *      --------------------------SQL提示---------------------
 *
 *      SQL提示，是优化数据库的一个重要手段，简单来说，就是在SQL语句中加入一些人为的提示来达到优
 *      化操作的目的。
 *
 *      use index ： 建议MySQL使用哪一个索引完成此次查询（仅仅是建议，mysql内部还会再次进行评估）。
 *
 *      语法：explain select * from tb_user use index(idx_user_pro) where profession = '软件工程';
 *
 *      ignore index ： 忽略指定的索引。
 *
 *      force index ： 强制使用索引。
 *
 *      --------------------------覆盖索引---------------------
 *
 *      尽量使用覆盖索引，减少select *。 那么什么是覆盖索引呢？ 覆盖索引是指 查询使用了索引，并且需要返回的列，
 *      在该索引中已经全部能够找到 。
 *
 *      在执行计划中我们主要关注的是后面的Extra的结果：
 *
 *      Using where; Using Index
 *      查找使用了索引，但是需要的数据都在索引列中能找到，所以不需要回表查询数据
 *
 *      Using index condition
 *      查找使用了索引，但是需要回表查询数据
 *
 *      一张表, 有四个字段(id, username, password, status), 由于数据量大, 需要对以下SQL语句进行优化,
 *      该如何进行才是最优方案
 *
 *      答：针对于 username, password建立联合索引
 *
 *      --------------------------前缀索引---------------------
 *
 *      当字段类型为字符串（varchar，text，longtext等）时，有时候需要索引很长的字符串，这会让索引变得很大，
 *      查询时，浪费大量的磁盘IO， 影响查询效率。此时可以只将字符串的一部分前缀，建立索引，这样可以大大节约索引空间，
 *      从而提高索引效率。
 *
 *      语法
 *      create index idx_xxxx on table_name(column(n));     n代表提取前n个字符建立索引
 *
 *      前缀长度：
 *      可以根据索引的选择性来决定，而选择性是指不重复的索引值（基数）和数据表的记录总数的比值，
 *      索引选择性越高则查询效率越高， 唯一索引的选择性是1，这是最好的索引选择性，性能也是最好的。
 *
 *      此字段重复的数量 / 此字段全部数量
 *      select count(distinct email) / count(*) from tb_user ;
 *
 *      //算出选择性
 *      select count(distinct substring(email,1,5)) / count(*) from tb_user ;
 *
 *      --------------------------单列索引与联合索引---------------------
 *
 *      单列索引：即一个索引只包含单个列
 *      联合索引：即一个索引包含了多个列
 *
 *      一个字段存在单列索引和联合索引时，而查询返回的条件又是多样的
 *      系统会自己选择索引而非理想的，可以通过SQL提示指定索引，最好使用覆盖索引，避免回表查询，用联合索引要返回的字段
 *
 *      在业务场景中，如果存在多个查询条件，考虑针对于查询字段建立索引时，建议建立联合索引，
 *      而非单列索引。
 *
 *      推荐使用联合索引
 *
 *      联合索引的B+树为字段相加的字符串，索引会导致最左前缀原则
 *
 *      --------------------------索引设计原则---------------------
 *      1.针对于数据量较大，且查询比较频繁的表建立索引。
 *      2. 针对于常作为查询条件（where）、排序（order by）、分组（group by）操作的字段建立索引。
 *      3. 尽量选择区分度高的列作为索引，尽量建立唯一索引，区分度越高，使用索引的效率越高。
 *      4. 如果是字符串类型的字段，字段的长度较长，可以针对于字段的特点，建立前缀索引。
 *      5. 尽量使用联合索引，减少单列索引，查询时，联合索引很多时候可以覆盖索引，节省存储空间，避免回表，提高查询效率
 *      6. 要控制索引的数量，索引并不是多多益善，索引越多，维护索引结构的代价也就越大，会影响增删改的效率。
 *           create unique index idx_user_phone_name on tb_user(phone,name);
 *      7. 如果索引列不能存储NULL值，请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时，
 *          它可以更好地确定哪个索引最有效地用于查询。
 *
 */

}
